﻿/*
 * OnlineAspParser - ASP.NET developer tool
 * Copyright (c) 2010, Bartłomiej Waluszko b.waluszko@hotmail.com
 * All Rights Reserved.
 * 
This file is part of OnlineAspParser.

OnlineAspParser is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

OnlineAspParser is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with OnlineAspParser; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;

namespace OnlineAspParser {
    public partial class Parser {

        /// <summary>
        /// Recursive parse control and children controls
        /// </summary>
        private string ParseWebControl(Control _control) {
            string output = "";

            output += "<div class=\"OnlineAspParser_Control\">";
            output += "<div class=\"OnlineAspParser_ControlTitle\"><b>" + _control.ClientID + "</b> - type:<b>" + _control.GetType().Name + "</b></div>";
            output += GetControlInfo(_control);

            if (_control.HasControls())
                foreach (Control item in _control.Controls)
                    output += ParseWebControl(item);

            output += "</div>";

            return output;
        }

        /// <summary>
        /// Return list of properties, type of string, bool, int of specified control
        /// </summary>
        private string GetControlInfo(Control control) {
            string output = "";

            //iterate all properties
            foreach (PropertyInfo item in control.GetType().GetProperties())
                try {
                    //names of properties who throws an error when I try print their value
                    if (item.Name == "IsValid" || item.Name == "InnerHtml" || item.Name == "InnerText" || item.Name == "TemplateSourceDirectory" || item.Name == "EnableTheming" || item.Name == "AppRelativeTemplateSourceDirectory" || item.Name == "CssClass" || item.Name == "CacheFileName" || item.Name == "CacheKey")
                        continue;

                    else if (item.PropertyType == typeof(bool))
                        output += item.Name + ":<b>" + control.GetType().GetProperty(item.Name).GetValue(control, null) as string + "</b>&nbsp;&nbsp; ";

                    else if (item.PropertyType == typeof(string)
                        && control.GetType().GetProperty(item.Name).GetValue(control, null) != null
                        && !string.IsNullOrEmpty((control.GetType().GetProperty(item.Name).GetValue(control, null) as string).Trim()))
                        output += item.Name + ":<b>" + HttpUtility.HtmlEncode(control.GetType().GetProperty(item.Name).GetValue(control, null) as string) + "</b>&nbsp;&nbsp; ";

                    else if (item.PropertyType == typeof(int))
                        output += item.Name + ":<b>" + control.GetType().GetProperty(item.Name).GetValue(control, null) + "</b>&nbsp;&nbsp; ";
                } catch (Exception ex) {
                    output += "Exception from GetControlInfo, property name: " + item.Name + ", message: " + ex.Message;
                }

            return output;
        }

        /// <summary>
        /// List of basic page properties and their values
        /// </summary>
        private string PropertiesList(Page _page) {
            string output = "";
            if (_page.Request.Params["ASP.NET_SessionId"] != null)
                output += "ASP.NET_SessionId: <b>" + _page.Request.Params["ASP.NET_SessionId"] + "</b><br/>";
            foreach (PropertyInfo item in _page.Request.GetType().GetProperties())
                try {
                    if (item.PropertyType == typeof(bool) ||item.PropertyType == typeof(int))
                        output += item.Name + ":<b>" + item.GetValue(_page.Request, null) + "</b><br/> ";

                    else if (item.PropertyType == typeof(string) 
                        && item.Name != "Item" 
                        && item.GetValue(_page.Request, null) is string 
                        && string.IsNullOrEmpty(item.GetValue(_page.Request, null).ToString().Trim())  )

                        output += item.Name + ":<b>" + HttpUtility.HtmlEncode(item.GetValue(_page.Request, null) as string) + "</b><br/> ";


                } catch (Exception ex) {
                    output += "Exception from PropertiesList, property name: " + item.Name + ", message: " + ex.Message;
                }

            return output;
        }

        /// <summary>
        /// Return keys and values of specified NameValueCollection
        /// </summary>
        private string GetNameValueCollection(NameValueCollection _nameValueCollection) {
            string output = "";
            foreach (string key in _nameValueCollection.Keys)
                if (key == "ALL_HTTP" || key == "ALL_RAW" || string.IsNullOrEmpty(_nameValueCollection[key].ToString()))
                    continue;
                else
                    output += key + ":<b>" + _nameValueCollection[key] + "</b><br/>";

            return output;
        }

        /// <summary>
        /// Renders information about view state
        /// </summary>
        private string GetViewState(Page _page) {
            

            string output = "";
            if (_page.Request.Form["__VIEWSTATE"] != null) {
                output+= "View state size: " + _page.Request.Form["__VIEWSTATE"].ToString().Length + " bytes, page total size: " +_page.Request.TotalBytes+" bytes <br/>";
                output += "View state string: " + _page.Request.Form["__VIEWSTATE"].ToString() + "<br/><hr/>";
                output += ParseViewStateGraph(new LosFormatter().Deserialize(_page.Request.Form["__VIEWSTATE"]), 0, "");

            } else
                output = "View State not found.<br/>ViewState visible only on POST request method";

            return output;
        }

        /// <summary>
        /// Renders information about cookies collection
        /// </summary>
        private string GetCookieCollection(HttpCookieCollection _cookies) {
            string output = "";
            if (_cookies.Count == 0)
                return "";
            foreach (string key in _cookies) {
                output += " Name:<b>" + (string.IsNullOrEmpty(_cookies[key].Name) ? "null" : _cookies[key].Name) + "</b><br/>";
                output += " Value:<b>" + (string.IsNullOrEmpty(_cookies[key].Value) ? "null" : _cookies[key].Value) + "</b>";
                output += (!string.IsNullOrEmpty(_cookies[key].Domain)) ? "Domain:<b>" + _cookies[key].Domain + "</b>" : "";
                output += " Expires: <b>" + _cookies[key].Expires + "</b>";
                output += " Has keys:<b>" + _cookies[key].HasKeys + "</b>";
                output += " HttpOnly:<b>" + _cookies[key].HttpOnly + "</b>";
                output += " Path:<b>" + (string.IsNullOrEmpty(_cookies[key].Path) ? "null" : _cookies[key].Path) + "</b>";
                output += " Secure:<b>" + _cookies[key].Secure + "</b>";

                output += "<br/><br/>";
                //output+=_cookies[key].


            }
            return output;
        }

        /// <summary>
        /// Recursively parses the view state.
        /// </summary>
        /// <param name="node">The current view state node.</param>
        /// <param name="depth">The "depth" of the view state tree.</param>
        /// <param name="label">A label to display in the emitted output next to the current node.</param>
        private string ParseViewStateGraph(object node, int depth, string label) {
            string output = "<br/>";


            if (node == null) {
                output += Indent(depth) + label + "NODE IS NULL";

            } else if (node is Triplet) {
                output += Indent(depth) + label + "TRIPLET";
                output += ParseViewStateGraph(((Triplet)node).First, depth + 1, "First: ");
                output += ParseViewStateGraph(((Triplet)node).Second, depth + 1, "Second: ");
                output += ParseViewStateGraph(((Triplet)node).Third, depth + 1, "Third: ");

            } else if (node is Pair) {
                output += Indent(depth) + label + "PAIR";
                output += ParseViewStateGraph(((Pair)node).First, depth + 1, "First: ");
                output += ParseViewStateGraph(((Pair)node).Second, depth + 1, "Second: ");

            } else if (node is ArrayList) {
                output += Indent(depth) + label + "ARRAYLIST";

                // display array values
                for (int i = 0; i < ((ArrayList)node).Count; i++)
                    output += ParseViewStateGraph(((ArrayList)node)[i], depth + 1, String.Format("({0}) ", i));

            } else if (node.GetType().IsArray) {
                output += Indent(depth) + label + "ARRAYLIST";
                output += "(" + node.GetType().ToString() + ")";
                IEnumerator e = ((Array)node).GetEnumerator();
                int count = 0;
                while (e.MoveNext())
                    output += ParseViewStateGraph(e.Current, depth + 1, String.Format("({0}) ", count++));

            } else if (node.GetType().IsPrimitive || node is string) {
                output += Indent(depth) + label;
                output += node.ToString() + " (" + node.GetType().ToString() + ")";

            } else {
                output += Indent(depth) + label + "OTHER - ";
                output += node.GetType().ToString();

            }
            return output;
        }

        /// <summary>
        /// Set indent in string in ParseViewStateGraph method
        /// </summary>
        private string Indent(int depth) {
            StringBuilder sb = new StringBuilder(indentString.Length * depth);
            for (int i = 0; i < depth; i++)
                sb.Append(indentString);
            return sb.ToString();
        } 
    }
}
